#include "user_uds.h"

#include "fm33lg0xx.h"
#include "fm33lg0xx_fl_flash.h"
#include "fm33lg0xx_fl_rmu.h"

#include <stdint.h>

UDS_SERVICE uds_status;

// 调换字节顺序
void endian_shift(uint8_t *source, uint32_t byte_num)
{
    uint32_t times  = 0;
    uint32_t i      = 0;
    uint8_t  buffer = 0;

    times = byte_num / 2;
    for (i = 0; i < times; i++) {
        buffer                     = source[i];
        source[i]                  = source[(byte_num - 1) - i];
        source[(byte_num - 1) - i] = buffer;
    }
}

// crc32校验初始化
static uint32_t crc32_init(uint8_t num)
{
    uint32_t poly = 0xEDB88320U; // reverse of 0x04C11DB7
    uint32_t r    = 0;
    uint8_t  j    = 0;

    r = num;
    for (j = 0; j < 8; j++) {
        r = (r >> 1) ^ (poly & ~((r & 1) - 1));
    }
    return r;
}

// crc32校验算法
uint32_t crc32_check(uint8_t *buf, uint32_t size, uint32_t crc)
{
    uint32_t        tablevalue = 0;
    uint8_t         cou        = 0;
    uint32_t        i          = 0;
    static uint32_t bak        = 0;

    bak += size;

    while (size != 0) {
        cou = (uint8_t)((buf[i]) ^ ((uint8_t)(crc & 0xFF)));
        i++;
        tablevalue = crc32_init(cou);
        crc        = tablevalue ^ (crc >> 8);
        --size;
    }
    return crc;
}

// 用户实现flash扇区擦除接口
uint8_t user_flash_n_sectors_Erase(uint32_t start_addr, uint16_t n_sectors)
{
    for (uint16_t i = 0; i < n_sectors; i++) {
        FL_FLASH_SectorErase(FLASH, start_addr + i * FLASH_SECTOR_SIZE);
    }
    return 1;
}

// 用户实现flash页擦除接口
uint8_t user_flash_n_page_erase(uint32_t addr, uint16_t n_page)
{
    for (uint16_t i = 0; i < n_page; i++) {
        if (FL_FLASH_PageErase(FLASH, addr + i * FLASH_PAGE_SIZE) == 0) {
            return 0;
        }
    }
    return 1;
}

// 用户实现flash单字接口
static uint8_t Flash_Write_1Word(uint32_t address, uint32_t dat)
{
    uint8_t status = FL_FLASH_Program_Word(FLASH, address, dat);
    if (status != 1) return 0;
    return 1;
}

// 用户实现flash字写接口
uint8_t user_flash_n_word_write(uint32_t addr, uint32_t *dat, uint16_t len)
{
    for (uint16_t i = 0; i < len; i++) {
        if (Flash_Write_1Word(addr + i * FLASH_PROGRAM_SIZE, *dat++) == 0) {
            return 0;
        }
    }
    return 1;
}

// ecu复位轮询
void Ecu_Reset_poll(void)
{

    if (uds_status.uds_sid11_service.soft_reset_timeout) {

        uds_status.uds_sid11_service.soft_reset_timeout--;

        if (uds_status.uds_sid11_service.soft_reset_timeout == 0) {

            // USER_UDS_LOG("SOFT RESET\n");
            /* 软复位MCU */
            FL_RMU_SetSoftReset(RMU);
        }
    }
}

// ecu擦除例程轮询
void Ecu_erase_poll(void)
{

    uint32_t flash_addr, flash_sector_size;

    if (uds_status.uds_sid31_service.erase_start_timeout) {

        uds_status.uds_sid31_service.erase_start_timeout--;

        if (uds_status.uds_sid31_service.erase_start_timeout == 0) {

            flash_addr = uds_status.uds_sid31_service.flash_erase_addr;

            flash_sector_size = (uds_status.uds_sid31_service.flash_erase_size / FLASH_ERASE_UNIT_BYTE);

            USER_UDS_LOG("flash addr:%x,%x\n", flash_addr, flash_sector_size);

            if (user_flash_n_sectors_Erase(flash_addr, flash_sector_size)) {

                USER_UDS_LOG("flash erase finish\n");

                uds_status.uds_sid31_service.erase_finish_flag = 1;
            }
        }
    }
}

void Ecu_check_mem_poll(void)
{

    uint32_t calc_crc;

    if (uds_status.uds_sid31_service.check_mem_start_timeout) {

        uds_status.uds_sid31_service.check_mem_start_timeout--;

        if (uds_status.uds_sid31_service.check_mem_start_timeout == 0) {

            // TODO: 这里需要重新计算整片APP2区域的CRC
            if (uds_status.uds_sid31_service.receive_crc32 == uds_status.uds_sid36_service.total_crc) {

                uds_status.uds_sid31_service.check_mem_finish_flag = 1;
            }
        }
    }
}

void uds_func_poll_task(void)
{

    Ecu_Reset_poll();

    Ecu_erase_poll();

    Ecu_check_mem_poll();
}
